(function(angular) {
	"use strict";
	angular.module("fs.waf").factory("loanInterestService", loanInterestService);
	loanInterestService.$inject = [ "modalService", "arithService", "formatService" ];
	function loanInterestService(modalService, arithService, formatService) {

		// init interest tab name, intcat value: res key, intcat label: res msg
		function initIntCatLabel(intCatOptions) {
			var intCatLabel = {};
			if (intCatOptions) {
				angular.forEach(intCatOptions, function(intcat, key) {
					intCatLabel[intcat.value] = intcat.label;
				});
			}
			return intCatLabel;
		}

		// convert loanInts list to loanIntObject object
		function initLoanIntObject(loan) {
			if (loan.loanInts) {
				loan.loanIntObject = loan.loanIntObject || {};
				angular.forEach(loan.loanInts, function(loanInt, key) {
					var intCat = loanInt.intCat;
					loan.loanIntObject[intCat] = loanInt;
					if (loan.loanIntObject[intCat].spreadTierList) {
						angular.forEach(loan.loanIntObject[intCat].spreadTierList, function(spreadTier, index) {
							spreadTier._intCat = intCat;
						});
					}
				});
			}
		}

		function initTierCriteria(loan, loanIntSpreadTierTypeOptionsBackUp, spreadTierInnerGridOptions, selectedSpreadTiers) {
			var reuslt = {};
			if (loan && loan.loanInts) {
				reuslt.loanIntSpreadTier2Column = {};

				angular.forEach(loan.loanInts, function(loanInt) {
					var intCat = loanInt.intCat;

					//					
					spreadTierInnerGridOptions[intCat].addRow = function(row) {
						row.hasFrontSameCriteria = "N";
						row._intCat = intCat;
					};
					spreadTierInnerGridOptions[intCat].removeSelectedRows = function() {
						if (loan.loanIntObject[intCat].spreadTierType2 && loan.loanIntObject[intCat].spreadTierType2 != "N") {
							angular.forEach(selectedSpreadTiers[intCat], function(selectedTier, key) {
								resetSpreadTierShow(selectedTier, loanInt.spreadTierList);
							});
						}
					};

					spreadTierInnerGridOptions[intCat].filterRowOperation = function(row, type) {
						if (row && row.entity && row.entity.hasFrontSameCriteria == "Y") {
							return true;
						} else {
							return false;
						}
					};

					spreadTierInnerGridOptions[intCat].addSubRow = function(row) {
						if (!loan.loanIntObject[row.entity._intCat].spreadTierType2 || loan.loanIntObject[row.entity._intCat].spreadTierType2 == "N") {
							modalService.openErrorDialogs({
								messages : [ "error.info.select-tiertype2" ]
							});
							return;
						}
						var _selectedTierCriteria;
						var _selectedTierCriteriaIndex;
						var selectedNum = 0;
						angular.forEach(loanInt.spreadTierList, function(spreadTier, index) {
							if (spreadTier.$$hashKey == row.entity.$$hashKey) {
								_selectedTierCriteria = spreadTier;
								_selectedTierCriteriaIndex = index;
								selectedNum = selectedNum + 1;
							}
						});

						var newTierCriteria = {};
						newTierCriteria._intCat = intCat;
						newTierCriteria.hasFrontSameCriteria = "Y";
						newTierCriteria.spreadTier = _selectedTierCriteria.spreadTier;
						loan.loanIntObject[row.entity._intCat].spreadTierList.splice(_selectedTierCriteriaIndex + 1, 0, newTierCriteria);
					};

					angular.forEach(spreadTierInnerGridOptions[intCat].columnDefs, function(colDef, index) {
						if (colDef && colDef.model == "spreadTier2") {
							reuslt.loanIntSpreadTier2Column[intCat] = colDef;
							spreadTierInnerGridOptions[intCat].columnDefs.splice(index, 1);
						}
					});

				});
			}
			return reuslt;
		}

		function formatCriteria(spreadTierInnerGridOptions, param, tier2) {
			var type = null, format = null, spreadTierType = null, modelName = null, options = null;
			if (tier2) {
				spreadTierType = param.spreadTierType2;
				modelName = "spreadTier2";
			} else {
				spreadTierType = param.spreadTierType;
				modelName = "spreadTier";
			}
			if (spreadTierType == "T" // Loan Tenor
					|| spreadTierType == "Y" // Day of Mth(1-31)
					|| spreadTierType == "K" // Day of Week(1-7)
					|| spreadTierType == "H" // Month (1-12)
					|| spreadTierType == "S" // Number of Days
					|| spreadTierType == "R" // Year (yyyy)
					|| spreadTierType == "E") {// Date (yyyymmdd)
				type = "number";
				format = "integer";
			} else if (spreadTierType == "A") { // Loan Out Amt
				type = "money";
				format = "vm.loan.loanInfo.loanCcy";
			} else if (spreadTierType == "U") { // Asset Amount
				type = "money";
				format = "vm.loan.asset.assetCcy";
			} else if (spreadTierType == "C") { // Credit Rating
				type = "percentage";
				format = "interestRate";
			}
			angular.forEach(spreadTierInnerGridOptions.columnDefs, function(colDef, index) {
				if (colDef && colDef.model == modelName) {
					colDef.type = type;
					colDef.format = format;
					if (options) {
						angular.merge(colDef.options, options);
					}
				}
			});

		}

		function deleteSpreadTierValue(spreadTierList, spreadTier) {
			if (spreadTierList) {
				angular.forEach(spreadTierList, function(spreadTier, index) {
					if (spreadTier == "spreadTier") { // delete tier
						delete spreadTier.spreadTier;
					} else if (spreadTier == "spreadTier2") { // delete tier2
						delete spreadTier.spreadTier2;
					}
				});
			}
		}

		function resetSpreadTierShow(selectedTier, spreadTierList) {
			if (selectedTier.hasFrontSameCriteria == "N") {
				var selectSpreadTier = false;
				for (var i = 0; i < spreadTierList.length; i++) {
					if (selectSpreadTier && spreadTierList[i].hasFrontSameCriteria == "Y" && selectedTier.spreadTier == spreadTierList[i].spreadTier) {
						spreadTierList[i].hasFrontSameCriteria = "N";
					}
					if (selectSpreadTier && spreadTierList[i].hasFrontSameCriteria == "N") {
						break;
					}
					if (selectedTier.$$hashKey == spreadTierList[i].$$hashKey) {
						selectSpreadTier = true;
					}
				}
			}
		}

		function formatAllInterstCriteria(spreadTierInnerGridOptions, loanInts) {
			if (loanInts) {
				angular.forEach(loanInts, function(loanInt, index) {
					formatCriteria(spreadTierInnerGridOptions[loanInt.intCat], loanInt);
					if (loanInt.spreadTierType2 && loanInt.spreadTierType2 != "N") {
						formatCriteria(spreadTierInnerGridOptions[loanInt.intCat], loanInt, true);
					}
				});
			}
		}

		/**
		 * reset TierCriteria for hasSameCriteria if spreadTierType2 isnot "N",
		 * then may be hidden hasSameCriteria if spreadTierType2 is "N", then
		 * open all hidden first columns
		 */
		function resetHasFrontSameCriteria(param) {
			var intCat = param.intCat;
			// need hidden some first column criteria
			if (param.spreadTierType != "N" && param.spreadTierType2 != "N") {
				if (param.spreadTierList && param.spreadTierList.length > 0) {
					var lastCriteria;
					for (var i = 0; i < param.spreadTierList.length; i++) {
						var spreadTierObject = param.spreadTierList[i];
						var spreadTier = spreadTierObject.spreadTier;
						if (!spreadTier) {
							continue;
						}
						if (param.spreadTierType == "T") {
							spreadTier = formatService.parseNumber(spreadTier);
						} else if (param.spreadTierType == "U" || param.spreadTierType == "A") {
							spreadTier = formatService.parseMoney(spreadTier);
						}
						if (i == 0) {
							lastCriteria = spreadTier;
							spreadTierObject.hasFrontSameCriteria = "N";
							continue;
						}
						//
						if (arithService.eq(spreadTier, lastCriteria)) {
							spreadTierObject.hasFrontSameCriteria = "Y";
						} else {
							spreadTierObject.hasFrontSameCriteria = "N";
						}
						spreadTierObject._intCat = intCat;

						lastCriteria = spreadTier;
					}
				}
			}
			// also need open hidden first column
			else if (param.spreadTierType != "N" && param.spreadTierType2 == "N") {
				if (param.spreadTierList && param.spreadTierList.length > 0) {
					for (var i = 0; i < param.spreadTierList.length; i++) {
						param.spreadTierList[i].hasFrontSameCriteria = "N";
						param.spreadTierList[i]._intCat = intCat;
					}
				}
			}
		}

		function loanIntRateChanged(loan, intCat) {
			var intRateSpread = loan.loanIntObject[intCat].intRateSpread_default;
			var intRateBase = loan.loanIntObject[intCat].intRateBase;
			var lpRateBase = loan.loanIntObject[intCat].lpRateBase;

			intRateSpread = intRateSpread ? intRateSpread : 0;
			intRateBase = intRateBase ? intRateBase : 0;
			lpRateBase = lpRateBase ? lpRateBase : 0;

			var rateType = loan.loanIntObject[intCat].intRateType;
			var rateSp = 0;
			var spreadTierType = loan.loanIntObject[intCat].spreadTierType;
			var spreadTierType2 = loan.loanIntObject[intCat].spreadTierType2;
			if (!spreadTierType || spreadTierType == "N")
				rateSp = intRateSpread;
			else {
				var baseAmt = 0, baseAmt2 = 0;
				if (spreadTierType == "T") {
					baseAmt = loan.loanInfo.tenorDays;
				} else if (spreadTierType == "A") {
					baseAmt = loan.loanInfo.loanAmt;
				} else if (spreadTierType == "U") {
					baseAmt = loan.asset.assetAmt;
				}
				if (spreadTierType2 && spreadTierType2 != "N") {
					if (spreadTierType2 == "T") {
						baseAmt2 = loan.loanInfo.tenorDays;
					} else if (spreadTierType2 == "A") {
						baseAmt2 = loan.loanInfo.loanAmt;
					} else if (spreadTierType2 == "U") {
						baseAmt2 = loan.asset ? loan.asset.assetAmt : 0;
					}
				}
				rateSp = getRate(loan, baseAmt, baseAmt2, intCat);
				loan.loanIntObject[intCat].intRateSpread_default = rateSp;
			}

			if (rateType == "P" || rateType == "A") {
				loan.loanIntObject[intCat].intSpreadTotal = 0;
				loan.loanIntObject[intCat].intRateFinal = 0;
				loan.loanIntObject[intCat].intBaseRateTotal = 0;
			} else {
				loan.loanIntObject[intCat].intSpreadTotal = rateSp;
				loan.loanIntObject[intCat].intRateFinal = arithService.add(arithService.add(rateSp, intRateBase), lpRateBase);
				loan.loanIntObject[intCat].intBaseRateTotal = arithService.add(intRateBase, lpRateBase);

			}
		}

		// for test tier1: group tier2: group detail
		function getRate(loan, amt, amt2, intCat) {
			var rate = 0;
			var spreadTierList = loan.loanIntObject[intCat].spreadTierList;
			if (spreadTierList) {
				var len = spreadTierList.length;
				var preTier = 0;
				var isTier = false;
				for (var i = 0; i < len; i++) {
					if (spreadTierList[i].spreadTier) {
						if (arithService.eq(spreadTierList[i].spreadTier, 0)) {
							break;
						}
						if (isTier && !arithService.eq(spreadTierList[i].spreadTier, preTier)) {
							break;
						}
						if (!arithService.gt(amt, spreadTierList[i].spreadTier)) {
							isTier = true;
							preTier = spreadTierList[i].spreadTier;
							rate = spreadTierList[i].spreadTierValue;
							rate = rate ? rate : 0;
							if (spreadTierList[i].spreadTier2) {
								if (!arithService.gt(amt2, spreadTierList[i].spreadTier2)) {
									break;
								}
							}
						}
					}
				}
			}
			return rate;
		}

		// set loan info to interest
		function setLoanInfoToInterest(loan) {
			if (loan.loanInts) {
				angular.forEach(loan.loanInts, function(loanInt) {
					loanInt.indexRefTenor = loan.loanInfo.indexRefTenor;
					loanInt.indexRefDate = loan.loanInfo.indexRefDate;
					loanInt.loanCcy = loan.loanInfo.loanCcy;
				});
			}
		}

		function loanIntSpreadTierType2Changed(loan, param, firstLoad, spreadTierInnerGridOptions, loanIntSpreadTier2Column) {
			var intCat = param.intCat, loanIntSpreadTierTypeOptions = [];
			angular.forEach(loan.loanIntSpreadTierTypeOptionsBackUp, function(spreadTierType, index) {
				if (spreadTierType.value != param.spreadTierType2) {
					loanIntSpreadTierTypeOptions.push(spreadTierType);
				}
			});
			if (!firstLoad) {
				deleteSpreadTierValue(loan.loanIntObject[intCat].spreadTierList, "spreadTier2");
			}
			if (param.spreadTierType2 && param.spreadTierType2 != "N") {
				// change tier table colmons
				var hasSpreadTier2Col = false;
				angular.forEach(spreadTierInnerGridOptions[intCat].columnDefs, function(colDef, index) {
					if (colDef && colDef.model == "spreadTier2") {
						hasSpreadTier2Col = true;
					}
				});
				if (!hasSpreadTier2Col) {
					angular.forEach(spreadTierInnerGridOptions[intCat].columnDefs, function(colDef, index) {
						if (colDef && colDef.model == "spreadTier") {
							spreadTierInnerGridOptions[intCat].columnDefs.splice(index + 1, 0, loanIntSpreadTier2Column[intCat]);
						}
					});
					// need hidden some first column criteria
					resetHasFrontSameCriteria(param);
				}
				// format by new spreadTierType2
				formatCriteria(spreadTierInnerGridOptions[intCat], param, true);
			} else if (param.spreadTierType2 == "N") {
				angular.forEach(spreadTierInnerGridOptions[intCat].columnDefs, function(colDef, index) {
					if (colDef && colDef.model == "spreadTier2") {
						spreadTierInnerGridOptions[intCat].columnDefs.splice(index, 1);
					}
				});
				// also need open hidden first column
				resetHasFrontSameCriteria(param);
			}
			return loanIntSpreadTierTypeOptions;
		}

		function loanIntCalcMethodChanged(loan, itemInterest) {
			var loanIntRateTypeOptions = [];
			for (var i = 0; i < loan.loanIntRateTypeOptionsAll.length; i++) {
				var _intType = loan.loanIntRateTypeOptionsAll[i];
				// Arrears (pay later)
				if (itemInterest.intCollMethod == "A") {
					if (_intType.value == "F" || _intType.value == "V" || _intType.value == "Y") {
						loanIntRateTypeOptions.push(loan.loanIntRateTypeOptionsAll[i]);
					}
				}
				// Prepaid (Discounting)
				else if (itemInterest.intCollMethod == "P") {
					if (_intType.value == "F" || _intType.value == "P" || _intType.value == "A" || _intType.value == "Y" || _intType.value == "N" || _intType.value == "S") {
						loanIntRateTypeOptions.push(loan.loanIntRateTypeOptionsAll[i]);
					}
				}
			}
			return loanIntRateTypeOptions;
		}

		function resetSpreadTierValue(loan, row) {
			var intCat = row._intCat;
			var spreadTierList = loan.loanIntObject[intCat].spreadTierList;
			var spreadTierValue = null;
			var selectSpreadTier = false;
			for (var i = 0; i < spreadTierList.length; i++) {
				var spreadTier = spreadTierList[i];
				if (spreadTier.hasFrontSameCriteria == "N") {
					if (selectSpreadTier) {
						break;
					}
					if (spreadTier.$$hashKey == row.$$hashKey) {
						spreadTierValue = spreadTier.spreadTier;
						selectSpreadTier = true;
					}
				} else if (spreadTier.hasFrontSameCriteria == "Y" && selectSpreadTier) {
					spreadTier.spreadTier = spreadTierValue;
				}
			}
		}

		function intRateSpread_defaultChanged(loan, itemInterest) {
			var intRateSpread = itemInterest.intRateSpread_default;
			var intRateBase = itemInterest.intRateBase;
			var lpRateBase = itemInterest.lpRateBase;

			intRateSpread = intRateSpread ? intRateSpread : 0;
			intRateBase = intRateBase ? intRateBase : 0;
			lpRateBase = lpRateBase ? lpRateBase : 0;
			var rateType = itemInterest.intRateType;
			var rateSp = 0;
			var spreadTierType = itemInterest.spreadTierType;
			var spreadTierType2 = itemInterest.spreadTierType2;
			if (!spreadTierType || spreadTierType == "N")
				rateSp = intRateSpread;
			else {
				var baseAmt = 0, baseAmt2 = 0;
				if (spreadTierType == "T") {
					baseAmt = loan.loanInfo.tenorDays;
				} else if (spreadTierType == "A") {
					baseAmt = loan.loanInfo.loanAmt;
				} else if (spreadTierType == "U") {
					baseAmt = loan.asset.assetAmt;
				}
				if (spreadTierType2 && spreadTierType2 != "N") {
					if (spreadTierType2 == "T") {
						baseAmt2 = loan.loanInfo.tenorDays;
					} else if (spreadTierType2 == "A") {
						baseAmt2 = loan.loanInfo.loanAmt;
					} else if (spreadTierType2 == "U") {
						baseAmt2 = loan.asset ? loan.asset.assetAmt : 0;
					}
				}
				rateSp = getRate(loan, baseAmt, baseAmt2, itemInterest.intCat);
				itemInterest.intRateSpread_default = rateSp;
			}

			if (rateType == "P" || rateType == "A") {
				itemInterest.intSpreadTotal = 0;
				itemInterest.intRateFinal = 0;
				itemInterest.intBaseRateTotal = 0;
			} else {
				itemInterest.intSpreadTotal = rateSp;
				itemInterest.intRateFinal = arithService.add(arithService.add(rateSp, intRateBase), lpRateBase);
				itemInterest.intBaseRateTotal = arithService.add(intRateBase, lpRateBase);
			}
		}

		function loanIntSpreadTierTypeChangedFunctions(loan, itemInterest, firstLoad, spreadTierInnerGridOptions) {
			if(itemInterest.spreadTierType && itemInterest.spreadTierType != "N"){
				loan.prodSubType.utIntSpread = 'N';
			}else{
				loan.prodSubType.utIntSpread = 'Y';
			}
			var intCat = itemInterest.intCat, loanIntSpreadTierType2Options = [];
			angular.forEach(loan.loanIntSpreadTierTypeOptionsBackUp, function(spreadTierType, index) {
				if (spreadTierType.value != itemInterest.spreadTierType) {
					loanIntSpreadTierType2Options.push(spreadTierType);
				}
			});

			// format by new spreadTierType
			if (itemInterest.spreadTierType && itemInterest.spreadTierType != "N") {
				formatCriteria(spreadTierInnerGridOptions[intCat], itemInterest);
			}

			if (firstLoad) {
				return loanIntSpreadTierType2Options;
			} else {
				deleteSpreadTierValue(itemInterest.spreadTierList, "spreadTier");
			}
			loanIntRateChanged(loan, intCat);
			return loanIntSpreadTierType2Options;
		}

		// update interest to loan info, then update all interest
		function updateInterestToLoanInfo(loan, itemInterest) {
			loan.loanInfo.indexRefTenor = itemInterest.indexRefTenor;
			loan.loanInfo.indexRefDate = itemInterest.indexRefDate;
			setLoanInfoToInterest(loan);
		}
		
		function setIntRateSpread(itemInterest){
			if(itemInterest.intRateType == "A"){
				itemInterest.intRateSpread = itemInterest.intRateSpread_a;
			}else if(itemInterest.intRateType == "P"){
				itemInterest.intRateSpread = itemInterest.intRateSpread_p;
			}else{
				itemInterest.intRateSpread = itemInterest.intRateSpread_default;
			}
		};
		
		function processInterest(loan){
			if(loan.loanInts){
				angular.forEach(loan.loanInts, function(itemInterest){
					setIntRateSpread(itemInterest);
				});
			}
		}

		return {
			initIntCatLabel : initIntCatLabel,
			initLoanIntObject : initLoanIntObject,
			initTierCriteria : initTierCriteria,
			formatCriteria : formatCriteria,
			formatAllInterstCriteria : formatAllInterstCriteria,
			resetHasFrontSameCriteria : resetHasFrontSameCriteria,
			loanIntRateChanged : loanIntRateChanged,
			getRate : getRate,
			setLoanInfoToInterest : setLoanInfoToInterest,
			loanIntSpreadTierType2Changed : loanIntSpreadTierType2Changed,
			loanIntCalcMethodChanged : loanIntCalcMethodChanged,
			resetSpreadTierValue : resetSpreadTierValue,
			intRateSpread_defaultChanged : intRateSpread_defaultChanged,
			loanIntSpreadTierTypeChangedFunctions : loanIntSpreadTierTypeChangedFunctions,
			updateInterestToLoanInfo : updateInterestToLoanInfo,
			processInterest : processInterest
		};

	}
})(angular);
